package com.iot08.admin.config.mob;

import com.alibaba.fastjson.JSONArray;
import com.iot08.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Connection;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;

import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * APP 的 accesstoken 之类的
 * @version 1.0
 * @Description:
 * @author: Rock
 * @time: 2020/9/7 11:27
 */
@Slf4j
@Component
public class RedisAccountClusterService {

    private static String serverAndPortListJSONStr;

    @Value("${redis.cluster.pool.serverAndPortListJSONStr}")
    public void setServerAndPortListJSONStr(String string){
        serverAndPortListJSONStr = string;
    }

    private static String password;
    @Value("${redis.cluster.pool.password}")
    public void setPassword(String string){
        password = string;
    }

    private static Integer poolMaxTotal;
    @Value("${redis.cluster.pool.maxTotal}")
    public void setPoolMaxTotal(Integer aPoolMaxTotal){
        poolMaxTotal = aPoolMaxTotal;
    }


    private static Integer poolMaxIdle;
    @Value("${redis.cluster.pool.maxIdle}")
    public void setPoolMaxIdle(Integer aPoolMaxIdle){
        poolMaxIdle = aPoolMaxIdle;
    }

    private static Integer poolMinIdle;
    @Value("${redis.cluster.pool.minIdle}")
    public void setPoolMinIdle(Integer aPoolMinIdle){
        poolMinIdle = aPoolMinIdle;
    }

    private static Long poolMaxWaitMillis;
    @Value("${redis.cluster.pool.maxWaitMillis}")
    public void setPoolMaxWaitMillis(Long aPoolMaxWaitMillis){
        poolMaxWaitMillis = aPoolMaxWaitMillis;
    }

    private static int soTimeout;
    @Value("${redis.cluster.soTimeout:5000}")
    public void setSoTimeout(int aSoTimeout){
        soTimeout = aSoTimeout;
    }

    private static int maxAttempts;
    @Value("${redis.cluster.maxAttempts:10}")
    public void setMaxAttempts(int aMaxAttempts){
        maxAttempts = aMaxAttempts;
    }

    private static Boolean poolTestOnBorrow;
    @Value("${redis.cluster.pool.testOnBorrow}")
    public void setPoolTestOnBorrow(Boolean aPoolTestOnBorrow){
        poolTestOnBorrow = aPoolTestOnBorrow;
    }

    private static Boolean poolTestOnReturn;
    @Value("${redis.cluster.pool.testOnReturn}")
    public void setPoolTestOnReturn(Boolean aPoolTestOnReturn){
        poolTestOnReturn = aPoolTestOnReturn;
    }



    private static JedisCluster jc;

    public synchronized static JedisCluster getJedisCluster() {
        if (jc != null) {
            return jc;
        }
        GenericObjectPoolConfig<Connection> config;
        Set<HostAndPort> jedisClusterNode;
        log.info("初始化 redis 集群实例配置数据: serverAndPortListJSONStr={}", serverAndPortListJSONStr);
        config = new GenericObjectPoolConfig();
        //最大连接数, 默认8个
        config.setMaxTotal(poolMaxTotal);
        // 最大空闲连接数, 默认8个
        config.setMaxIdle(poolMaxIdle);
        // 最小空闲连接数, 默认8个
        config.setMinIdle(poolMinIdle);
        // 当池内没有对象返回时，最大的等待时间
        config.setMaxWaitMillis(poolMaxWaitMillis);
        // 当调用borrow Object方\法时，是否进行有效性检查
        config.setTestOnBorrow(poolTestOnBorrow);
        // 当调用return Object方法时，是否进行有效性检查
        config.setTestOnReturn(poolTestOnReturn);

        if (StringUtil.isBlank(password)) {
            password = null;
        }

        //集群结点

        jedisClusterNode = new HashSet<HostAndPort>();
        JSONArray hostAndPortList = JSONArray.parseArray(serverAndPortListJSONStr);
        for (int i = 0; i < hostAndPortList.size(); i++) {
            String item = hostAndPortList.getString(i);
            String host = item.split(":")[0];
            String port = item.split(":")[1];
            jedisClusterNode.add(new HostAndPort(host, Integer.valueOf(port)));

        }

        /*
        JedisCluster(
        Set<HostAndPort> jedisClusterNode,
         int connectionTimeout,
          int soTimeout, //返回值的超时时间  毫秒
          int maxAttempts, //出现异常最大重试次数
          String password,
          final GenericObjectPoolConfig poolConfig //配置
                      */

        jc = new JedisCluster(jedisClusterNode, 15000, soTimeout, maxAttempts, password, config);
//
//
//        log.info("JedisCluster={} ", jc.toString());
        return jc;
    }

    /**
     * @param key
     * @param value
     * @time: 2020/11/2 16:30
     * @author: Rock
     * @version 1.0
     */
    public String set(String key, String value) {
        JedisCluster jedis = getJedisCluster();
        
        if (jedis != null) {
            try {
                return jedis.set(key, value);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param second
     * @param value
     * @time: 2020/11/4 11:29
     * @author: Rock
     * @version 1.0
     */
    public String setex(String key, int second, String value) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.setex(key, second, value);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @time: 2020/11/2 16:31
     * @author: Rock
     * @version 1.0
     */
    public String get(String key) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.get(key);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param field
     * @time: 2020/10/17 10:17
     * @author: Rock
     * @version 1.0
     */
    public String hget(String key, String field) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.hget(key, field);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }


    /**
     * 获取多个 hex Map 的值
     * @param key
     * @param fields
     * @time: 2021/08/25 15:17
     * @author: Weichao
     * @version 1.0
     */
    public List<String> hmget(String key, String... fields) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.hmget(key, fields);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param field
     * @param value
     * @time: 2020/9/25 14:19
     * @author: Rock
     * @version 1.0
     */
    public Long hset(String key, String field, String value) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.hset(key, field, value);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }

    /**
     * 更新后原来的失效时间不会改变
     *
     * @param key
     * @param value
     */
    public void updateValue(String key, String value) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                long expire = jedis.ttl(key);
                jedis.setex(key, expire, value);

            } finally {
                //jedis.close();
            }
        }
    }

    /**
     * @param key
     * @param field
     * @time: 2020/9/25 14:20
     * @author: Rock
     * @version 1.0
     */
    public Long hdel(String key, String field) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.hdel(key, field);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @time: 2020/10/20 11:17
     * @author: Rock
     * @version 1.0
     */
    public Long del(String key) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.del(key);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }

    /**
     * @param keys
     * @time: 2020/10/20 11:17
     * @author: WeiChao
     * @version 1.0
     */
    public Long mdel(String... keys) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.del(keys);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }


    /**
     * @param key
     * @time: 2021/1/15 11:09
     * @author: Rock
     * @version 1.0
     */
    public Map<String, String> hgetAll(String key) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.hgetAll(key);
            } finally {
                //jedis.close();
            }
        }
        return null;
    }

    /**
     * @param key
     * @param value
     * @time: 2021/1/15 11:23
     * @author: Rock
     * @version 1.0
     */
    public void hmset(String key, Map<String, String> value) {
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                jedis.hmset(key, value);
            } finally {
                //jedis.close();
            }
        }
    }

//    /**
//     * @param key
//     * @time: 2021/2/26 9:10
//     * @author: Rock
//     * @version 1.0
//     */
//    public Set<String> keys(String key) {
//        JedisCluster jedis = getJedisCluster();
//        if (jedis != null) {
//            try {
//                return jedis.keys(key);
//            } finally {
//                //jedis.close();
//            }
//        }
//        return null;
//    }

    public Boolean exists(String... key){
        JedisCluster jedis = getJedisCluster();
        if (jedis != null) {
            try {
                return jedis.exists(key) > 0;
            } finally {
                //jedis.close();
            }
        }
        return false;
    }

}
